#define _GNU_SOURCE
#include "app_pool.h"
#include <mqueue.h>
#include <pthread.h>
#include <stdlib.h>
#include <stdio.h>
#define MAX_SZIE 1024

static mqd_t mqd;
static char *queue_name = "/app_pool_mq";
static pthread_t *threads;
static int thread_num;

/*在分线程中执行的函数,从消息队列中接收信息*/
void *thread_func(void *arg)
{
    Task task;
    //char func_entrance[sizeof(Task)] = {0};
    while (1)/*不断从消息队列中取出任务的入口地址并执行*/
    {
        /*我们使用char型的指针接收消息队列中的数据，本质上还是拿到任务函数的入口地址*/
        ssize_t rs = mq_receive(mqd, (char*)&task, sizeof(Task), 0);
        //task=*(Task*)func_entrance;
        if(rs==sizeof(task)){
            task.func(task.arg);
        }
    }
}

/*初始化线程池和任务*/
int app_pool_Init(int size)
{
    /*创建消息队列*/
    struct mq_attr attr;
    attr.mq_maxmsg = 10;
    attr.mq_msgsize = sizeof(Task);
    mqd = mq_open(queue_name, O_CREAT | O_RDWR, 0644, &attr);
    if (mqd == -1)
    {
        printf("mq ERROR\n");
        return -1;
    }

    /*创建线程池*/
    thread_num = size;
    /*给线程池分配空间*/
    threads=(pthread_t*)malloc(sizeof(pthread_t)*thread_num);
    for (int i = 0; i < thread_num; i++)
    {
        pthread_create(threads+i, NULL, thread_func, NULL);
    }
    
    
    return 0;
}

/*关闭*/
void app_pool_close(void){
    /*关闭并删除消息队列*/
    mq_close(mqd);
    mq_unlink(queue_name);

    /*清除线程池中的线程*/
    for(int i=0;i<thread_num;i++){
        pthread_cancel(threads[i]);
        pthread_join(threads[i],NULL);
    }
    free(threads);
}

/*注册任务*/
void app_pool_registerTask(Task_Func func, void *arg){
    Task* task=(Task*)malloc(sizeof(Task));
    task->func=func;
    task->arg=arg;
    int rs=mq_send(mqd,(char*)task,sizeof(Task),0);/*复制任务数据到消息队列中，因为进程间的地址空间是相互独立的*/
    free(task);
}